home *** CD-ROM | disk | FTP | other *** search
- // -*- C++ -*-
-
- /* Simple argument-parsing class
- * Copyright (C) 2001 Patrick E. Pelletier <ppelleti@users.sourceforge.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
- #ifdef WIN32
- #pragma warning( disable : 4786 )
- #endif // WIN32
-
- #include <string>
- #include <vector>
-
- class ArgParseInternalData; // hide implementation details
-
- /*
- * The ArgParse class allows you to specify names of options
- * that you want parsed, along with a usage message for them.
- * Options come in four flavors: flag, int, float, and string.
- * Flags don't take arguments, but the other kinds do. For
- * an option that takes an argument, it can be specified with
- * an equals sign, with a colon, or by putting it in the next
- * element of argv. ("--foo=stuff", "--foo:stuff", or
- * "--foo stuff", respectively)
- *
- * The flavors that take arguments also come in array flavors.
- * With an array, you specify a pointer to a vector of the basic
- * type, instead of just a pointer to a basic type. This allows
- * the option to appear more than once, and the new values are
- * appended to the array. Optionally, you can also specify a
- * separator character, so that multiple array elements can be
- * parsed up from a single instance of the option.
- *
- * Options can start with either a single dash or a double dash,
- * but see allowOneCharOptionsToBeCombined() for more information.
- *
- * The argument "--" all by itself signals the end of the options,
- * and everything after it will go into the leftovers (see leftovers())
- * even if it starts with a dash.
- *
- * The usage text for an option gets appended immediately after the
- * name of the option and its aliases. The ASCII BEL character (\a)
- * can be used as a special kind of tab, which moves the cursor to
- * the current indent level (see usageHeader()), to make it easy to
- * make things line up in columns.
- */
-
- /*
- * Rationale for some design decisions:
- *
- * Things which need to be modified are passed as pointers, not as
- * references, because some people feel that non-const references make
- * what's going on less clear, and I kind of agree with them.
- *
- * Arrays are explicitly passed as std::vector (or whatever you change
- * the typedefs below to) instead of passing around iterators and
- * allowing any STL container to be used, just because unnecessary
- * templatization can be less clear and sometimes leads to portability
- * and debugability issues, and doesn't seem justified for this simple
- * application.
- */
-
- class ArgParse
- {
- public:
- // Basic types: ArgParse always uses these typedefs, so that there's
- // just one place to change things if you want to use float instead
- // of double, or CqString instead of std::string, etc.
- typedef bool apflag;
- typedef int apint;
- typedef double apfloat;
- typedef std::string apstring;
-
- // Array types: ditto
- typedef std::vector<apint> apintvec;
- typedef std::vector<apfloat> apfloatvec;
- typedef std::vector<apstring> apstringvec;
-
- // These two constants are valid values for the "separator"
- // argument to argInts, argFloats, and argStrings. (Any ASCII
- // character is also a valid argument.) SEP_NONE means that the
- // only way to get more than one thing in the array is to specify
- // the option more than once. (e. g. "--foo one --foo two")
- // SEP_ARGV means that each element of argv, up to the next option,
- // will be put into the array. (e. g. "--foo one two") Using an
- // ASCII character means that only one argv element is used, but
- // it can become multiple elements in the array by being split
- // on the given character. (e. g. "--foo one,two")
- enum {
- SEP_NONE = -1,
- SEP_ARGV = -2
- };
-
- ArgParse();
- ~ArgParse();
-
- // Calling this method means that "-bar" will be treated as if
- // it was "-b -a -r", and to specify a multi-character option,
- // you need to use a double dash. (e. g. "--bar") If you don't
- // call this method, then single dash and double dash are treated
- // the same.
- void allowOneCharOptionsToBeCombined(); // long but descriptive :)
-
- // Normally, parse() will return an error if there are any
- // unrecognized options. But if you call this method before
- // calling parse(), then unrecognized options will go into
- // the leftovers, without causing an error.
- void allowUnrecognizedOptions();
-
- // "--foo" will set *value to true. If allow_negation is true,
- // then "--nofoo" will set *value to false.
- void argFlag(apstring name, apstring usage,
- apflag* value, bool allow_negation = true);
-
- void argInt(apstring name, apstring usage, apint* value);
- void argInts(apstring name, apstring usage,
- apintvec* values, int separator = SEP_NONE, int count = -1);
-
- void argFloat(apstring name, apstring usage, apfloat* value);
- void argFloats(apstring name, apstring usage,
- apfloatvec* values, int separator = SEP_NONE, int count = -1);
-
- void argString(apstring name, apstring usage, apstring* value);
- void argStrings(apstring name, apstring usage,
- apstringvec* values, int separator = SEP_NONE, int count = -1);
-
- // Makes "aliasname" work just like "realname". Note that
- // "realname" can be a negated flag name (if the flag allows
- // negation), so you can make "--fooless" mean "--nofoo", for
- // example.
- void alias(apstring realname, apstring aliasname);
-
- // This inserts literal text into the usage message. The order
- // is significant with respect to calls to argFlag, argInt, etc.
- // The most common use of this would be to add the
- // "Usage: blech [options] files" at the top, but it can also be
- // used to make different "sections" of options (give the --help
- // option to GNU tar to see what I mean) or to make a footer at the
- // end of the usage. Your string can contain newlines, but it
- // shouldn't end in a newline unless you want an extra blank line.
- // The "indent" value specifies how to line up
- // columns of individual usage messages in the follow section.
- // (Again, refer to the GNU tar usage message to see what I mean.)
- void usageHeader(apstring text, int indent = 25);
-
- // This makes the parsing actually happen. Returns true on
- // success, or false on failure.
- bool parse(int argc, const char** argv);
-
- // If parse() returns false, this method will give you an
- // error message that describes what's wrong. Note that
- // although it's legal to call parse() more than once on the
- // same ArgParse object, only the most recent error message is
- // retained.
- apstring errmsg() const;
-
- // Returns a usage string made up of the usage messages of
- // the individual arguments, with things from usageHeader()
- // interspersed at the appropriate places. The string returned
- // contains embedded newlines, and also a trailing newline.
- apstring usagemsg() const;
-
- // Returns any leftover arguments. (arguments which didn't start
- // with a dash and didn't get eaten by another option, or any
- // arguments which appeared after "--")
- // Again, this is only valid until the next call to parse() on
- // this ArgParse object.
- const apstringvec& leftovers() const;
-
- private:
- ArgParseInternalData* d;
- };
-